package
{
	import flash.display.*;
	import flash.events.*;
	import flash.text.*;
	import flash.geom.*;
	import flash.utils.getTimer;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.display.StageScaleMode;
	public class TopDownDrive extends MovieClip
	{
		private static const SPEED:Number = .3;
		private static const TURN_SPEED:Number = .2;
		private static const CAR_SIZE:Number = 50;
		private static const MAP_RECT:Rectangle = new Rectangle( -1150, -1150, 2300, 2300);
		private static const NUM_TRASH:int = 50;//垃圾数目
		private static const MAX_CARRY:uint = 10;//最大携带量
		private static const PICKUP_DIS:Number = 30;//拾起距离
		private static const DROP_DIS:Number = 40;//倒垃圾时车与垃圾箱距离
		
		private var blocks:Array;//车不可到达的范围
		private var trashObjects:Array;//所有垃圾
		private var trashcans:Array;//垃圾箱
		private var arrowLeft, arrowRight, arrowUp, arrowDown:Boolean;//按键状态
		
		private  var lastTime:int;
		private var gameStartTime:int;//游戏开始了多长时间
		private var onboard:Array;
		private var totalTrashObjects:int;
		private var score:int;
		private var lastObject:Object;
		//sounds
		private var theHornSound:HornSound = new HornSound();
		private var theGotOneSound:GotOneSound = new GotOneSound();
		private var theDumpSound:DumpSound = new DumpSound();
		private var theFullSound:FullSound = new FullSound();
		public function TopDownDrive()
		{
			super();
		}
		public function startTopDownDrive()
		{
			arrowDown = false;
			arrowLeft = false;
			arrowRight = false;
			arrowUp = false;
			score = 0;	
			gameStartTime = getTimer();
			findBlocks();
			placeTrash();
			trashcans = new Array(gamesprite.Trashcan1, gamesprite.Trashcan2, gamesprite.Trashcan3);
			gamesprite.setChildIndex(gamesprite.car, gamesprite.numChildren - 1);
			addEventListener(Event.ENTER_FRAME, gameLoop);
			stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownFunction);
			stage.addEventListener(KeyboardEvent.KEY_UP, keyUpFunction);
			onboard = new Array(0, 0, 0);
			showScore();
		}
		private function gameLoop(evt:Event):void
		{
			if (lastTime == 0)	lastTime = getTimer();
			var timeDiff:int = getTimer() - lastTime;
			lastTime += timeDiff;
			if (arrowLeft)
			{
				rotateCar(timeDiff,"left");
			}
			if (arrowRight)
			{
				rotateCar(timeDiff,"right");
			}
			if (arrowUp)
			{
				moveCar(timeDiff);
				centerMap();
				checkCollisions();
			}
			if (arrowDown)
			{
				moveCar(timeDiff, 'back');
				centerMap();
				checkCollisions();
			}
			showTime();
		}
		private function centerMap()
		{
			gamesprite.x = -gamesprite.car.x + 286;
			gamesprite.y = -gamesprite.car.y + 220;
		}
		private function checkCollisions()
		{
			for (var i:int = trashObjects.length - 1; i >= 0; i-- )
			{
				if (Point.distance(new Point(gamesprite.car.x, gamesprite.car.y), new Point(trashObjects[i].x, trashObjects[i].y)) < PICKUP_DIS)
				{
					
					if (totalTrashObjects < MAX_CARRY)
					{	
						onboard[trashObjects[i].currentFrame-1]++;
						gamesprite.removeChild(trashObjects[i]);
						trashObjects.splice(i, 1);
						showScore();
						playSound(theGotOneSound);
					}
					else if (trashObjects[i] != lastObject)
					{
						playSound(theFullSound);
						lastObject = trashObjects[i];
					}
				}
			}
			for (i = 0; i < trashcans.length; i++ )
			{
				if (Point.distance(new Point(gamesprite.car.x, gamesprite.car.y),
						new Point(trashcans[i].x, trashcans[i].y)) < DROP_DIS)
				{
					if (onboard[i] > 0)
					{
						score += onboard[i];
						onboard[i] = 0;
						showScore();
						playSound(theDumpSound);
						if (score >= NUM_TRASH)
						{
							endGame();
							break;
						}
					}
				}
			}
		}
		private function showTime()
		{
			var gameTime:int = getTimer() - gameStartTime;
			timeDisplay.text = clockTime(gameTime);
		}
		private function clockTime(ms:int):String
		{
			var seconds:int = Math.floor(ms / 1000);
			var minutes:int = Math.floor(seconds / 60);
			seconds -= minutes * 60;
			var timeString:String = minutes + ":" + String(seconds + 100).substr(1, 2);
			return timeString;
		}
		private function showScore()
		{
			totalTrashObjects = 0;
			for (var i:int = 0; i < 3; i++ )
			{
				this["onboard" + (i + 1)].text = String(onboard[i]);
				totalTrashObjects += onboard[i];
			}
			for (i = 0; i < 3; i++ )
			{
				if (totalTrashObjects >= 10)
				{
					this["onboard" + (i + 1)].textColor = 0xFF0000;
				}
				else
				{
					this["onboard" + (i + 1)].textColor = 0xFFFFFF;
				}
			}
			numLeft.text = String(trashObjects.length);
			scoreDisplay.text = String(score);
		}
		private function endGame()
		{
			blocks = null;
			trashObjects = null;
			trashcans = null;
			this.removeEventListener(Event.ENTER_FRAME, gameLoop);
			stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyDownFunction);
			stage.removeEventListener(KeyboardEvent.KEY_UP, keyUpFunction);
			gotoAndStop("gameover");
		}
		private function showFinalMessage()
		{
			showTime();
			var finalDisplay:String = timeDisplay.text;
			finalMessage.text = finalDisplay;
		}
		private function playSound(soundObj:Object)
		{
			var channel:SoundChannel = soundObj.play();
		}
		private function rotateCar(timeDiff:Number, direction:String)
		{
			if (direction == "left")
			{
				gamesprite.car.rotation -= TURN_SPEED * timeDiff;
			}
			else if (direction == "right")
			{
				gamesprite.car.rotation += TURN_SPEED * timeDiff;
			}
		}
		private function moveCar(timeDiff:Number,direction:String="forward")
		{
			var carRect = new Rectangle(gamesprite.car.x - CAR_SIZE / 2,
							gamesprite.car.y - CAR_SIZE / 2, CAR_SIZE, CAR_SIZE);
			var newCarRect:Rectangle = carRect.clone();
			var carAngle:Number = (gamesprite.car.rotation / 180) * Math.PI;
			if (direction == "back")
			{
				carAngle = ((gamesprite.car.rotation + 180) / 180) * Math.PI;
			}
			var dx:Number = Math.cos(carAngle);
			var dy:Number = Math.sin(carAngle);
			newCarRect.x += dx * SPEED * timeDiff;
			newCarRect.y += dy * SPEED * timeDiff;
			var newX:Number = gamesprite.car.x + dx * SPEED * timeDiff;
			var newY:Number = gamesprite.car.y + dy * SPEED * timeDiff;
			for (var i:int = 0; i < blocks.length; i++ )
			{
				var blockRect:Rectangle = blocks[i].getRect(gamesprite);
				if (blockRect.intersects(newCarRect))
				{
					if (carRect.right <= blockRect.left)
					{
						newX += blockRect.left - newCarRect.right;
					}
					else if (carRect.left >= blockRect.right)
					{
						newX += blockRect.right - newCarRect.left;
					}
					if (carRect.top >= blockRect.bottom)
					{
						newY += blockRect.bottom - newCarRect.top;
					}
					else if (carRect.bottom <= blockRect.top)
					{
						newY += blockRect.top - newCarRect.bottom;
					}
				}
			}
			if ((newCarRect.right > MAP_RECT.right) && (carRect.right <= MAP_RECT.right))
			{
				newX += MAP_RECT.right - newCarRect.right;
			}
			if ((newCarRect.left<MAP_RECT.left) && (carRect.left>=MAP_RECT.left))
			{
				newX += MAP_RECT.left - newCarRect.left;
			}
			if ((newCarRect.top<MAP_RECT.top) && (carRect.top>=MAP_RECT.top))
			{
				newY += MAP_RECT.top - newCarRect.top;
			}
			if ((newCarRect.bottom > MAP_RECT.bottom) && (carRect.bottom <= MAP_RECT.bottom))
			{
				newY += MAP_RECT.bottom - newCarRect.bottom;
			}
			gamesprite.car.x = newX;
			gamesprite.car.y = newY;
		}
		private  function findBlocks()
		{
			blocks = new Array();
			for (var i = 0; i < gamesprite.numChildren; i++ )
			{
				var mc = gamesprite.getChildAt(i);
				if (mc is Block)
				{
					blocks.push(mc);
					mc.visible = false;
				}
			}
		}
		private function placeTrash()
		{
			trashObjects = new Array();
			for (var i:int = 0; i < NUM_TRASH; i++ )
			{
				while (1)
				{
					var trash_x:int = Math.floor(Math.random() * MAP_RECT.width) + MAP_RECT.x;
					var trash_y:int = Math.floor(Math.random() * MAP_RECT.height) + MAP_RECT.y;
					var isOnBlock:Boolean = false;
					for (var j:int = 0; j < blocks.length; j++ )
					{
						if (blocks[j].hitTestPoint(trash_x + gamesprite.x, trash_y + gamesprite.y))
						{
							isOnBlock = true;
							break;
						}
					}
					if (!isOnBlock)
					{
						var newObject:TrashObject = new TrashObject();
						newObject.x = trash_x;
						newObject.y = trash_y;
						newObject.gotoAndStop(Math.floor(Math.random() * 3) + 1);
						gamesprite.addChild(newObject);
						trashObjects.push(newObject);
						break;
					}
				}
			}
		}
		private function keyDownFunction(evt:KeyboardEvent):void
		{
			if (evt.keyCode == 37)
			{
				arrowLeft = true;
			}
			else if (evt.keyCode == 38)
			{
				arrowUp = true;
			}
			else if (evt.keyCode == 39)
			{
				arrowRight = true;
			}
			else if (evt.keyCode == 40)
			{
				arrowDown = true;
			}
		}
		private function keyUpFunction(evt:KeyboardEvent):void
		{
			if (evt.keyCode == 37)
			{
				arrowLeft = false;
			}
			else if (evt.keyCode == 38)
			{
				arrowUp = false;
			}
			else if (evt.keyCode == 39)
			{
				arrowRight = false;
			}
			else if (evt.keyCode == 40)
			{
				arrowDown = false;
			}
		}
	}
}